package cn.xo68.boot.job.jdbcstore.lock;

import cn.xo68.boot.job.entity.DistributedLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class DistributedLockManager {
    private static final Logger logger=LoggerFactory.getLogger(DistributedLockManager.class);

    public static final long CHECK_INTERVAL_SECONDS=300L;

    @Autowired
    private DistributedLockStore distributedLockStore;

    /**
     * 尝试加锁
     * @param lockKey 锁主键
     * @param lockHold 锁持有者
     * @param timeout 锁超时时间，单位：毫秒
     * @param waitMillis 锁等待时间，单位：毫秒
     * @return
     */
    public DistributedLock tryLock(String lockKey, String lockHold, long timeout, long waitMillis){
        DistributedLock lock=null;
        if(timeout < 50){
            timeout=50;
        }
        if(waitMillis > timeout){
            waitMillis = timeout;
        }
        long waitTime=0L;
        while (lock==null && waitTime < waitMillis){
            try{
                lock=distributedLockStore.tryLock(lockKey, lockHold, timeout);
            }catch (Exception e){
                logger.debug("操作锁存储状态异常,{} 锁已经存在了", lockKey);
                if(logger.isTraceEnabled()){
                    logger.error("操作锁存储状态异常",e);
                }
                lock=null;
            }

            if(lock==null){
                waitTime+=CHECK_INTERVAL_SECONDS;
                try {
                    Thread.sleep(CHECK_INTERVAL_SECONDS);
                } catch (InterruptedException e) {
                    //e.printStackTrace();
                }
            }
        }

        if(lock!=null && logger.isDebugEnabled()){
            logger.debug("申请锁成功，{}", lockKey);
        }

        return lock;
    }

    public void unLock(String lockKey){
        try{
            distributedLockStore.unLock(lockKey);
            logger.debug("释放锁成功，{}", lockKey);
        }catch (Exception e){
            logger.error("释放分布式锁异常", e);
        }
    }
}
